import random  # 导入随机数模块，用于生成随机值防止缓存
from PIL import Image  # 导入PIL图像处理库，用于裁剪验证码图片
import requests  # 导入HTTP请求库，用于网络通信
import io  # 导入字节流处理模块，用于内存中操作图片数据
import ddddocr  # 导入OCR识别库，专门处理验证码识别

session = requests.Session()  # 创建会话对象，自动保持cookies，维持登录状态

# 初始化ddddocr实例，det=False(不检测文字), ocr=False(不识别文字), show_ad=False(不显示广告)
# 此配置专用于滑动验证码缺口检测
slide = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False)

value = random.random()  # 生成0-1之间的随机小数，作为验证码请求参数防止缓存

# 发送GET请求获取验证码图片，URL参数带上随机值确保每次请求新图片
res = session.get(f'https://bm.ruankao.org.cn/sign/captchaImg? {value}')

print(session.cookies)  # 打印当前会话的cookies，查看服务器返回的会话标识

# 以二进制写入模式打开文件，将验证码图片保存到本地
with open(f"./tu/yzm/three.png", "wb") as f:
    f.write(res.content)  # 将响应内容(图片二进制数据)写入文件

three_img = Image.open(f"./tu/yzm/three.png")  # 打开保存在本地的验证码图片

# 背景图 - 从原图中裁剪出验证码背景区域(坐标:左0上0右240下150)
background_img = three_img.crop((0, 0, 240, 150))
background_bytes = io.BytesIO()  # 创建内存字节流对象，用于临时存储图片
background_img.save(background_bytes, format='PNG')  # 将背景图保存到内存字节流

# background_img.save("./static/slide/background_img.png")  # 保存背景图到文件(已注释)
# background_img.show()  # 弹出窗口显示背景图(已注释)

# 从原图裁剪出滑块目标图(坐标:左0上151右50下300)，即需要拖动的缺口图片
target_img = three_img.crop((0, 151, 50, 300))
target_bytes = io.BytesIO()  # 创建内存字节流对象
target_img.save(target_bytes, format='PNG')  # 将目标图保存到内存字节流
# target_img.show()  # 显示目标图(已注释)

# full_img = three_img.crop((0, 301, 240, 450))  # 裁剪完整图(已注释，本例未使用)
# full_bytes = io.BytesIO()  # 创建字节流(已注释)
# full_img.save(full_bytes, format='PNG')  # 保存完整图(已注释)
# full_img.show()  # 显示完整图(已注释)

# 使用ddddocr进行滑动验证码缺口检测，返回目标位置的像素坐标
res_slide = slide.slide_match(target_bytes.getvalue(), background_bytes.getvalue())
print(f"边缘检测", res_slide['target'][0])  # 打印检测到的水平偏移量(缺口左边距)
offset = res_slide['target'][0]  # 提取偏移量，用于后续验证

# res_slide = slide.slide_comparison(background_bytes.getvalue(), full_bytes.getvalue())  # 使用图像对比法(已注释)
# print(f"图像对比", res_slide['target'][0])  # 打印对比结果(已注释)

# 2. 开始验证 - 向服务器发送偏移量验证验证码是否正确
res = session.get(f'https://bm.ruankao.org.cn/sign/checkTnCode?p= {offset}')
print(res.json())  # 打印验证结果JSON
print(session.cookies)  # 打印验证后的cookie变化

# 3. 开始请求 - 使用验证通过的验证码数据进行登录
res  = session.post("https://bm.ruankao.org.cn/sign/inok ", data={
"s1":"NDEwNTI3MTk5MDEyMjM0NDIzNAasdfgasdf==",  # 登录参数1，可能是加密后的用户名
"s2":"350c9d901b7f1c73a481e240ec1b7c000000b",  # 登录参数2，可能是加密后的密码
"s3":offset  # 登录参数3，使用前面获取的验证码偏移量
})

print(res.json())  # 打印最终登录结果
